#pragma once
#include <iostream>
#include <poll.h>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstring>

using namespace std;

class TcpServer
{
public:
    const static int N = 1024;
    TcpServer(uint16_t port)
        :_port(port), _listensock(-1)
    {
        // 创建tcp套接字
        _listensock = socket(AF_INET, SOCK_STREAM, 0);
        if(_listensock < 0)
        {
            cout << "socket error" << endl;
            exit(1);
        }
        cout << "create socket success, _listensock: " << _listensock << endl;
        // 填写结构体信息
        struct sockaddr_in local;
        memset(&local, 0, sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = htons(_port);
        local.sin_addr.s_addr = INADDR_ANY;
        // 绑定IP和PORT
        int n = bind(_listensock, (struct sockaddr*)&local, sizeof(local));
        if(n < 0)
        {
            cout << "bind error" << endl;
            exit(2);
        }
        cout << "bind success, _listensock: " << _listensock << endl;
        // 监听
        n = listen(_listensock, 16);
        if(n < 0)
        {
            cout << "listen error" << endl;
            exit(2);
        }
        cout << "listen success, _listensock: " << _listensock << endl;

        // 初始化数组
        for(int i=0; i<N; i++)
        {
            _events[i].fd = -1;
            _events[i].events = 0;
            _events[i].revents = 0;
        }
        // _listensock初始化
        _events[0].fd = _listensock;
        _events[0].events = POLLIN;
        _events[0].revents = 0;
    }

    void AcceptClient()
    {
        struct sockaddr_in peer;
        socklen_t len = sizeof(peer);
        int sockfd = accept(_listensock, (struct sockaddr*)&peer, &len);
        if(sockfd < 0) return;
        int pos = 1;
        for(; pos < N; pos++)
        {
            // 有空出来的，可以给sockfd占用
            if(_events[pos].fd == -1) break;
        }
        if(pos == N)
        {
            // 扩容或close
        }
        else
        {
            // sockfd添加
            _events[pos].fd = sockfd;
            _events[pos].events = POLLIN;
            _events[pos].revents = 0;
            cout << "sockfd add success, sockfd: " << sockfd << endl;
        }
    }

    void Service(int i)
    {
        char buffer[1024];
        ssize_t n = recv(_events[i].fd, buffer, sizeof(buffer)-1, 0);
        if(n > 0)
        {
            buffer[n] = 0;
            cout << "client msg: " << buffer << endl;
            string str = "[echo msg]# ";
            str += buffer;
            send(_events[i].fd, str.c_str(), str.size(), 0);
        }
        else if(n == 0)
        {
            close(_events[i].fd);
            _events[i].fd = -1;
            _events[i].events = 0;
            _events[i].revents = 0;
            cout << "recv quit" << endl;
        }
        else 
        {
            close(_events[i].fd);
            _events[i].fd = -1;
            _events[i].events = 0;
            _events[i].revents = 0;
            cout << "recv error" << endl;
        }
    }

    // 处理fd就是接收新连接(accept), _listensock已经就绪
    void handler()
    {
        // 不一定只有一个fd(_listensock), 可能有多个
        for(int i=0; i<N; i++)
        {
            if(_events[i].fd == -1) continue;
            int fd = _events[i].fd;
            short revents = _events[i].revents;
            // 判断是读还是写(这里我们暂时只有读), 读写分离
            if(revents & POLLIN)
            {
                if(fd == _listensock)
                {
                    AcceptClient();
                }
                else 
                {
                    Service(i); // 注意传的是i
                }
            }
            if(revents & POLLOUT)
            {
                // 暂时不做处理
            }
        }
    }
    void Loop()
    {
        while(true)
        {
            int n = poll(_events, 1024, -1);
            if(n > 0)
            {
                cout << "处理就绪fd" << endl;
                handler();
            }
            else if(n == 0)
            {
                cout << "poll timeout" << endl;
            }
            else
            {
                cout << "poll error" << endl;
            }
        }
    }
    ~TcpServer()
    {
        if (_listensock > -1)
            close(_listensock);
    }

private:
    uint16_t _port;
    int _listensock;

    // pollfd结构体
    struct pollfd _events[N];
};